home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 476-500 / disk_496 / ruler / workbench / ruler.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  15KB  |  637 lines

  1. /*    RULER - Workbench Version
  2.  *
  3.  *    See Ruler.doc for directions
  4.  *
  5.  *    Revision History:
  6.  *    -----------------
  7.  *
  8.  *    Version 5.0   21-Apr-1991  ©1991 Dave Schreiber, Chad Netzer, and
  9.  *                     Thad Floryan
  10.  *        Based upon code from:
  11.  *
  12.  *    Version 4.0   29-Dec-1989  ©1989  Chad Netzer and Thad Floryan
  13.  *
  14.  *        Based upon code, idea, and logic from:
  15.  *
  16.  *    Version 1.0   7-Nov-1988   ©1988 Thad Floryan
  17.  *
  18.  *    Revision history:
  19.  *        21-April-1991 - (Ver. 5.00) (DKS):
  20.  *        1 Window is sized to make room for > 8 point fonts in the
  21.  *          title bar and main window (for compatibility with AmigaOS
  22.  *          2.x)
  23.  *        2 Added the ability to put Ruler's window on any screen at
  24.  *          will.
  25.  *        3 Added the ability to get the font scale from any window.
  26.  *        4 Added menus for:
  27.  *          * About
  28.  *          * Quit
  29.  *          * Change Screen (#2)
  30.  *          * Change Font (#3)
  31.  *          These menus are layed out by the 2.x function
  32.  *          LayoutMenusA().  This function is called only if Ruler
  33.  *          is running under 2.0 or later (i.e. Ruler is 1.3
  34.  *          compatible).
  35.  *
  36.  *        29-December-1989 - (Ver. 4.0) - Added an offset so that you can
  37.  *        just stick the window on the left edge of the workbench screen,
  38.  *        and it will automatically be lined up with the characters.
  39.  *        Fixed some more minor bugs and rearranged the code a bit.
  40.  *        Added ARP support for those who want it. (CFN)
  41.  *
  42.  *        09-March-1989 - (Ver. 3.1) - Fixed a visual bug so that scale can
  43.  *        no longer be less than eight. (CFN)
  44.  *
  45.  *        06-Dec-1988 - (Ver. 3.0) - Added support for measuring fonts of
  46.  *        varying widths (selectable scale). (CFN)
  47.  *
  48.  *        22-Nov-1988 - (Ver. 2.2) - More adjustments to code, No major
  49.  *        changes.  Program size is slightly smaller.  (CFN)
  50.  *
  51.  *        14-Nov-1988 - (Ver. 2.1) - Fixed a few minor (harmless) bugs.  The
  52.  *        right edge of the ruler is now always redrawn after resizing.
  53.  *        I got rid of that GOTO statement (which in 'C', is considered a
  54.  *        bug. :-)  Version 2.1 now lets you open a ruler to be as low as
  55.  *        12 characters wide, which 2.0 only advertised. (CFN)
  56.  *
  57.  *        13-Nov-1988 - (Ver. 2.0) - I added minor enhancements, most
  58.  *        noteably, the ability to resize the window, and support for
  59.  *        overscanned screens.    (CFN)
  60.  *
  61.  *
  62.  *    Feel welcome to use this program for any non-commercial purposes or
  63.  *    for your personal learning.  Commercial users are requested to contact
  64.  *    Thad at either:
  65.  *
  66.  *    UUCP:    thad@cup.portal.com (OR) ..!sun!portal!cup.portal.com!thad
  67.  *    BBS:    BBS-JC, 415/961-7250 (300/1200/2400), "Thad Floryan" | "SYSOP"
  68.  *
  69.  *    Chad at:
  70.  *
  71.  *    UUCP:    chad@ucscb.ucsc.edu    (during school term)
  72.  *    UUCP:    chad@cup.portal.com    (holidays, summer, etc.)
  73.  *    BBS:    BBS-JC, 415/961-7250 (300/1200/2400), "Chad Netzer"
  74.  *
  75.  *    or Dave at:
  76.  *
  77.  *    UUCP:    davids@ucscb.ucsc.edu
  78.  *    BBS:    BBS-JC, "Dave Schreiber"
  79.  *
  80.  *
  81.  *    Building instructions (SAS/C V5.10):
  82.  *
  83.  *          lc -Lcd -v Ruler
  84.  *
  85.  */
  86.  
  87. #include <exec/types.h>
  88. #include <exec/memory.h>
  89. #include <intuition/intuition.h>
  90. #include <intuition/intuitionbase.h>
  91. #include <graphics/gfxbase.h>
  92. #include <workbench/startup.h>
  93. #include <clib/wb_protos.h>
  94.  
  95. #define AMIGA_2.0 1    /*Delete if include files for 2.0 or later are*/
  96.             /*not available*/
  97.  
  98. #ifdef AMIGA_2.0
  99.  
  100. #include <utility/tagitem.h>
  101.  
  102. struct TagItem menuTag[] =
  103. {
  104.    {TAG_DONE,NULL}
  105. };
  106.  
  107. #endif
  108.  
  109. #include "GUI.h"
  110.  
  111.    /*Some constants*/
  112. #define HEIGHT titleBarHeight+textHeight-2
  113. #define DEF_HEIGHT 12L+HEIGHT
  114. #define RULER_MARK_Y 11L+HEIGHT
  115. #define OFFSET_START_Y 2L+titleBarHeight
  116. #define BIG_TIC_Y 5L+HEIGHT
  117. #define SMALL_TIC_Y 9L+HEIGHT
  118. #define TEXT_Y 3L+HEIGHT
  119. #define DRAW_AREA_Y 3L+titleBarHeight
  120. #define DRAW_AREA_HEIGHT 24L+textHeight
  121.  
  122. #define NEW(typ)                AllocMem((ULONG)sizeof(typ), MEMF_CLEAR)
  123. #define FREE(p,typ)             FreeMem(p,(ULONG)sizeof(typ))
  124.  
  125. #define ever (;;)       /* used for infinite loops */
  126.  
  127. #define FATAL 20    /* exit code */
  128. #define WARN  10    /* exit code */
  129. #define NORMAL 0    /* exit code */
  130.  
  131. #define LEFT_OFFSET 3L    /* "dead space" on left side of ruler margin */
  132.  
  133. extern void    *OpenLibrary();
  134. extern void    *OpenWindow();
  135. extern void    *GetMsg();
  136. extern void    *AllocMem();
  137. extern void    ReplyMsg();
  138.  
  139. /* Prototypes for functions defined in ruler5.c */
  140. void __regargs release_resources(void);
  141. void __regargs error_exit(void);
  142. int  __regargs handleMenu(USHORT NUM);
  143. void __regargs printAboutWindow(void);
  144. void __regargs changeFSize(void);
  145. void __regargs changeScreen(void);
  146. void __regargs readWBArgs(void);
  147.  
  148. UWORD        titleBarHeight,textHeight,textWidth,screenWidth;
  149.  
  150. struct NewWindow window_def =
  151. {
  152.     0, 0,              /* Initial LeftEdge, TopEdge */
  153.     241, 17,        /* Default pixel-width, pixel-height */
  154.     0, 1,            /* DetailPen, BlockPen */
  155.     CLOSEWINDOW    |    /* IDCMP flags */
  156.     MENUPICK    |
  157.     NEWSIZE,
  158.     WINDOWDRAG    |    /* window flags */
  159.     WINDOWDEPTH    |
  160.     WINDOWCLOSE    |
  161.     WINDOWSIZING    |
  162.     ACTIVATE    |
  163.     SMART_REFRESH    |
  164.     NOCAREREFRESH,
  165.     NULL,            /* Gadget list */
  166.     NULL,            /* checkmark stuff */
  167.     NULL,            /* window title (to be filled in later) */
  168.     NULL,            /* custom screen pointer */
  169.     NULL,            /* bitmap pointer */
  170.     97 + LEFT_OFFSET, 0,    /* Minwidth, no MinHeight */
  171.     -1, 0,            /* no MaxWidth, MaxHeight */
  172.     CUSTOMSCREEN        /* screen type */
  173. };
  174.  
  175. struct Window        *window;
  176. struct RastPort     *rp;
  177. struct IntuitionBase    *IntuitionBase;
  178. struct GfxBase        *GfxBase;
  179. struct Library        *GadToolsBase;
  180. struct Library        *IconBase;
  181.  
  182. struct Screen        *screen;
  183. struct IntuiMessage    *sys_message;
  184. ULONG            class;
  185. USHORT            code;
  186. int            resource_state;
  187. long    fsize;        /* The font size of ruler scale */
  188. long    w;        /* character width of ruler    */
  189.  
  190. APTR            visualInfo;
  191.  
  192. char *version =
  193.     "Text Ruler   V5.00 (Workbench)   21-Apr-91  ©1991                            ";
  194.  
  195. extern struct WBStartup *WBenchMsg;
  196.  
  197. /**********************************************************************/
  198.  
  199. _main ()
  200. {
  201.  
  202.     long    fivec;        /* pixel size of five chars    */
  203.     long    w_lim;        /* pixel width (w * fsize)      */
  204.     long    x;        /* present window x coordinate    */
  205.     long    y;        /* present window y coordinate    */
  206.  
  207.     char    buf[5];
  208.  
  209.     int    redoWindow;    /*Boolean flag*/
  210.  
  211.     resource_state = 0;
  212.  
  213. /*
  214.  *    Open Intuition and Graphics so we can get screen size and
  215.  *    default font information.
  216.  */
  217.     if((IntuitionBase = OpenLibrary ("intuition.library", NULL))==NULL)
  218.         error_exit();
  219.     ++resource_state;
  220.  
  221.     if((GfxBase = OpenLibrary ("graphics.library", NULL))==NULL)
  222.         error_exit();
  223.     ++resource_state;
  224.  
  225.     GadToolsBase = OpenLibrary("gadtools.library",NULL);
  226.     if(GadToolsBase)
  227.        window_def.IDCMPFlags|=(ACTIVEWINDOW|INACTIVEWINDOW);
  228.  
  229. /*
  230.  *    Get WorkBench screen information
  231.  */
  232.     screen=window_def.Screen=IntuitionBase->ActiveScreen;
  233.  
  234.     w = 30L;    /* default ruler is 30 chars for a filename */
  235.      /*Get default scale*/
  236.     fsize=textWidth=GfxBase->DefaultFont->tf_XSize;
  237.  
  238.     readWBArgs();
  239.     w_lim = w * fsize;
  240.  
  241. /*
  242.  *    Main loop
  243.  */
  244.  
  245.     for ever
  246.     {
  247.  
  248. /*    Get width of screen
  249.  */
  250.         screenWidth=screen->Width;
  251.  
  252. /*    Determine spacing from current font information
  253.  */
  254.         titleBarHeight = screen->Font->ta_YSize;
  255.         textHeight = GfxBase->DefaultFont->tf_YSize;
  256.  
  257. /*
  258.  *    Now calculate window sizing and placement parameters and setup title.
  259.  */
  260.         window_def.Width    = w_lim + LEFT_OFFSET + 1;
  261.         window_def.Height    = DEF_HEIGHT;
  262.         window_def.Title    = (UBYTE *)version;
  263. /*
  264.  *    Shorten the window if it would be wider than the screen
  265.  */
  266.         if (window_def.Width > screenWidth )
  267.         {
  268.            window_def.Width = screenWidth;
  269.            w_lim = (window_def.Width) - 1 - LEFT_OFFSET;
  270.         }
  271.  
  272. /*
  273.  *    Open the ruler display window.
  274.  */
  275.         window = OpenWindow (&window_def);
  276.  
  277.         if (window == NULL)
  278.         {
  279.         error_exit();
  280.         }
  281.         ++resource_state;
  282.  
  283. /*
  284.  *    Set screen and window titles
  285.  */
  286.         SetWindowTitles(window,version,"Text Ruler V5.00");
  287.  
  288. /*
  289.  *    If running under 2.0 or later, adjust menu spacing information
  290.  *    to compensate for a non-8 point font size.
  291.  */
  292.         if(GadToolsBase != NULL)
  293.         {
  294.            visualInfo = (APTR)GetVisualInfoA(screen,menuTag);
  295.            LayoutMenusA(&Menu1,visualInfo,menuTag);
  296.            FreeVisualInfo(visualInfo);
  297.         }
  298.  
  299. /*
  300.  *    Install menus
  301.  */
  302.         SetMenuStrip(window,&Menu1);
  303. /*
  304.  *    Get pointer to raster port.
  305.  */
  306.         rp = window -> RPort;
  307.  
  308. /*
  309.  *    Inner loop (loop until the window needs to be closed and another
  310.  *    opened).
  311.  */
  312.         redoWindow=FALSE;
  313.  
  314.         while(!redoWindow)
  315.         {
  316.         redoWindow=FALSE;
  317.         fivec        = 5L * fsize;
  318. /*
  319.  *    Use RectFill to blank the window area and set pen for drawing.
  320.  */
  321.         SetAPen(rp, NULL);
  322.         RectFill(rp, LEFT_OFFSET+1, DRAW_AREA_Y, w_lim + LEFT_OFFSET-1,
  323.               DRAW_AREA_Y+DRAW_AREA_HEIGHT);
  324. /*
  325.  *    Now set pen to draw.
  326.  */
  327.         SetAPen(rp, 1L);
  328. /*
  329.  *    When I use the ruler, I like to jam it up against the left hand side of
  330.  *    my workbench screen, so that it to measure something on the CLI.
  331.  *    However, the CLI is offset by a small amount, so I compensate by
  332.  *    starting the "virtual" area of the ruler a little to the right...
  333.  *
  334.  *    Fill in the offset area that is unused.
  335.  */
  336.  
  337.         RectFill(rp, NULL, OFFSET_START_Y, LEFT_OFFSET,
  338.             DRAW_AREA_Y+DRAW_AREA_HEIGHT+1);
  339.  
  340. /*
  341.  *    Draw ruler and text
  342.  */
  343.         for (x = NULL; x < (w_lim + fsize); x += fsize)
  344.         {
  345.             /*big tic every 5 chars*/
  346.             if ((x % fivec) == NULL)  y = BIG_TIC_Y;
  347.             else y = SMALL_TIC_Y;     /* small tic every char  */
  348.             Move (rp, x + LEFT_OFFSET, y);
  349.             Draw (rp, x + LEFT_OFFSET, RULER_MARK_Y);
  350. /*
  351.  *    Label ruler.
  352.  *    The test for position `fivec' (in the Move()) is for centering ``5''
  353.  *    differently than the centering for two-digit numbers.
  354.  */
  355.             if ((x > NULL) && (x < w_lim) && ((x % fivec) == NULL))
  356.             {
  357.             stci_d(buf,x/fsize);
  358.             Move (rp, (x == fivec)
  359.                ? (x - textWidth + (textWidth/2) + LEFT_OFFSET)
  360.                : (x -  textWidth + LEFT_OFFSET),
  361.                TEXT_Y);
  362.             Text (rp, buf, (long) strlen (buf));
  363.             }
  364.         }
  365.  
  366.         SetAPen(rp,1);
  367.         Move(rp,w_lim+LEFT_OFFSET,titleBarHeight);
  368.         Draw(rp,w_lim+LEFT_OFFSET,DEF_HEIGHT);
  369.  
  370. /*
  371.  *    Wait for gadget activation.  No busy-/spin-/wait-loops here!
  372.  */
  373.         Wait (1L << window -> UserPort -> mp_SigBit);
  374. /*
  375.  *    Retrieve LAST message in Message Port
  376.  */
  377.         sys_message = GetMsg(window -> UserPort);
  378.         class = sys_message -> Class;
  379.         code = sys_message -> Code;
  380.         ReplyMsg(sys_message);
  381. /*
  382.  *    Dump uneeded messages (respond only to the last on LIFO queue).
  383.  */
  384.         while (sys_message = GetMsg(window -> UserPort))
  385.         {
  386.             ReplyMsg(sys_message);
  387.         }
  388.  
  389.              /*Handle various IDCMP events*/
  390.         switch(class)
  391.         {
  392.             case CLOSEWINDOW:
  393.             release_resources();
  394.             exit (NORMAL);
  395.  
  396.             case NEWSIZE:
  397.             w_lim = (window -> Width) - 1 - LEFT_OFFSET;
  398.             break;
  399.  
  400.             case INACTIVEWINDOW:
  401.             SetWindowTitles(window,version,"Text Ruler V5.00");
  402.             break;
  403.  
  404.             case MENUPICK:
  405.             redoWindow=handleMenu(code);
  406.         }
  407.         }
  408.     }
  409. }
  410.  
  411. /**********************************************************************
  412.  *
  413.  *    cleanup routine
  414.  *
  415.  *    The ``switch'' on resource_state is to assure we don't attempt to
  416.  *    free something we don't have.  Items are released in the reverse
  417.  *    order they were obtained (by "falling thru" the cases).
  418.  */
  419. void __regargs release_resources()
  420. {
  421.     switch (resource_state)
  422.     {
  423.         case 3: ClearMenuStrip(window);
  424.             CloseWindow (window);
  425.         case 2: CloseLibrary(GfxBase);
  426.         case 1: CloseLibrary(IntuitionBase);
  427.     }
  428.     if(GadToolsBase != NULL)
  429.        CloseLibrary(GadToolsBase);
  430. }
  431.  
  432. /**********************************************************************
  433.  *
  434.  *    error handler
  435.  */
  436. void __regargs error_exit()
  437. {
  438.     release_resources();
  439.     exit (FATAL);
  440. }
  441.  
  442. /*
  443.  *    Decode menu choice
  444.  */
  445.  
  446. int __regargs handleMenu(USHORT NUM)
  447. {
  448.    struct MenuItem *item;
  449.    USHORT menuNum,itemNum;
  450.  
  451.    while(NUM != MENUNULL)
  452.    {
  453.       menuNum=MENUNUM(NUM);
  454.       itemNum=ITEMNUM(NUM);
  455.       item=(struct MenuItem *)ItemAddress(&Menu1,NUM);
  456.  
  457.       if(menuNum==0)
  458.      if(itemNum==0)
  459.         printAboutWindow();     /*About*/
  460.      else
  461.      {
  462.         release_resources();    /*Quit*/
  463.         exit(NORMAL);
  464.      }
  465.       else
  466.      if(itemNum==0)
  467.      {
  468.         changeFSize();          /*Change Scale*/
  469.         return(FALSE);
  470.      }
  471.      else
  472.      {
  473.         changeScreen();         /*Change Screen*/
  474.         return(TRUE);
  475.      }
  476.  
  477.       NUM=item->NextSelect;
  478.    }
  479.    return(0);
  480. }
  481.  
  482. /*
  483.  *    Display the About window
  484.  */
  485. void __regargs printAboutWindow()
  486. {
  487.    struct Window *aboutWdw;
  488.  
  489.    if((NewAboutWindow.LeftEdge=(screenWidth-NewAboutWindow.Width)/2) > 200)
  490.       NewAboutWindow.LeftEdge = 200;
  491.  
  492. /*
  493.  *    Determine About window position
  494.  */
  495.    NewAboutWindow.TopEdge=(screen->Height-NewAboutWindow.Height)/5;
  496.    NewAboutWindow.Height=titleBarHeight-15+ABOUT_WDW_HEIGHT;
  497.  
  498. /*
  499.  *    Get the screen the about window will appear on (same as the
  500.  *    screen the main window is on).
  501.  */
  502.    NewAboutWindow.Screen = (struct Screen *) screen;
  503.  
  504. /*
  505.  *    Open window
  506.  */
  507.  
  508.    aboutWdw=(struct Window *)OpenWindow(&NewAboutWindow);
  509.    if(aboutWdw==NULL)
  510.       return;
  511.  
  512. /*
  513.  *    Print window text
  514.  */
  515.  
  516.    PrintIText(aboutWdw->RPort,&IText11,0,titleBarHeight-15);
  517.  
  518. /*
  519.  *    Wait for input close gadget to be pressed, then close window and
  520.  *    return.
  521.  */
  522.    Wait(1<<aboutWdw->UserPort->mp_SigBit);
  523.  
  524.    CloseWindow(aboutWdw);
  525.    return;
  526. }
  527.  
  528. /*
  529.  *    Change scale
  530.  */
  531. void __regargs changeFSize()
  532. {
  533.    ULONG IDCMPFlags;
  534.  
  535.    IDCMPFlags=window_def.IDCMPFlags;
  536.    ModifyIDCMP(window,INACTIVEWINDOW);
  537.  
  538.    for ever
  539.    {
  540.        /*Wait for IDCMP event*/
  541.        Wait (1L << window -> UserPort -> mp_SigBit);
  542.        sys_message = GetMsg(window -> UserPort);
  543.        class = sys_message -> Class;
  544.        ReplyMsg(sys_message);
  545.  
  546. /*
  547.  *     If another window was clicked, get the horizontal font size of
  548.  *     the current font in that window
  549.  */
  550.  
  551.        if(class==INACTIVEWINDOW)
  552.        {
  553.      if((IntuitionBase->ActiveWindow->RPort->Font->tf_Flags & FPF_PROPORTIONAL) == 0)
  554.         fsize=IntuitionBase->ActiveWindow->RPort->Font->tf_XSize;
  555.      else
  556.      {
  557.         /*If the window is using a proportional font, print an error*/
  558.         SetWindowTitles(window,version,"Can't change scale:  window font is proportional.");
  559.         DisplayBeep(window->WScreen);
  560.      }
  561.      ModifyIDCMP(window,IDCMPFlags);
  562.      return;
  563.        }
  564.    }
  565. }
  566.  
  567. /*
  568.  *    Change the screen that the window is displayed on.
  569.  */
  570.  
  571. void __regargs changeScreen()
  572. {
  573.    for ever
  574.    {
  575. /*
  576.  *    Wait for user to click on another window (hopefully in another
  577.  *    screen).
  578.  */
  579.        ModifyIDCMP(window,INACTIVEWINDOW);
  580.        Wait (1L << window -> UserPort -> mp_SigBit);
  581.        sys_message = GetMsg(window -> UserPort);
  582.        class = sys_message -> Class;
  583.        ReplyMsg(sys_message);
  584.        if(class==INACTIVEWINDOW)
  585.        {
  586.      /*Get active screen*/
  587.      window_def.Screen=screen=IntuitionBase->ActiveScreen;
  588.  
  589.      /*Clear menu strip and close window*/
  590.      ClearMenuStrip(window);
  591.      CloseWindow(window);
  592.      resource_state--;
  593.  
  594.      return;
  595.        }
  596.    }
  597. }
  598.  
  599.  /*Get arguments from Ruler's icon*/
  600. void __regargs readWBArgs()
  601. {
  602.    char  *Arg;
  603.    struct DiskObject *obj;
  604.  
  605.       /*Open library*/
  606.    IconBase=(struct IconBase *)OpenLibrary("icon.library",0L);
  607.    if(IconBase == NULL)
  608.    {
  609.       release_resources();
  610.       exit(200);
  611.    }
  612.  
  613.       /*Get the icon's information*/
  614.    obj=GetDiskObject(WBenchMsg->sm_ArgList[0].wa_Name);
  615.  
  616.       /*Check for size tool type*/
  617.    Arg=FindToolType(obj->do_ToolTypes,"size");
  618.    if(Arg != NULL)
  619.       w=atol(Arg);
  620.  
  621.       /*Check for scale tool type*/
  622.    Arg=FindToolType(obj->do_ToolTypes,"scale");
  623.    if(Arg != NULL)
  624.       fsize=atol(Arg);
  625.  
  626.       /*Check to make sure everything's in bounds*/
  627.    if(fsize < 5 || fsize > 50 || w < 12)
  628.       exit(300);
  629.  
  630.       /*Free the allocated disk object*/
  631.    FreeDiskObject(obj);
  632.  
  633.    CloseLibrary(IconBase); /*Close the icon library*/
  634.    return;
  635. }
  636.  
  637.